package excelBase;

import java.util.ArrayList;
import java.util.HashMap;

import lib.SheetInLib;
import lib.WorkbookInLib;
import main.ErrorException;
import main.ErrorHandler;
import main.WarningHandler;
import script.Script;
import define.Common;
import define.Config;
import define.ErrorDefine;
import define.ExcelType;
import define.WarningDefine;

public class ExcelFile extends BaseContent
{
	private WorkbookInLib m_workBook;
	private ArrayList<Script> m_scripts;
	private String m_scriptSheetName;
	private String m_path;
	private Sheet m_scriptSheet;
	private short m_notAttributeBGColor;
	private short m_notAttributeFGColor;
	private HashMap<ExcelType, ArrayList<String>> m_sheetNames;
	private ExcelType m_type;
	
	public ExcelFile(String fileName) throws ErrorException
	{
		super(Common.getWithoutExtendName(fileName));
		m_children = new ArrayList<>();
		m_path = Common.m_path;
		m_workBook = new WorkbookInLib(fileName);
		m_scriptSheetName = Common.m_scriptSheet;	
		m_scriptSheet = null;
		m_type = null;
		m_sheetNames = new HashMap<>();
		for(ExcelType type: ExcelType.values())
		{
			m_sheetNames.put(type, null);
		}
	}
	
	public void init() throws ErrorException
	{
		int len = m_workBook.getSheetNumber();
		SheetInLib sheetInLib = m_workBook.getSheet(m_scriptSheetName);
		if(sheetInLib == null)
		{
			throw new ErrorException(ErrorDefine.E_NO_SCRIPT_ERROR, m_scriptSheetName, Config.NO_POSITION);
		}
		m_scriptSheet = new Sheet(sheetInLib, ExcelType.E_TABLE_EXT, this);
		m_scriptSheet.init();
		Head head = m_scriptSheet.getHead(Config.COLOR_HEAD);
		m_notAttributeBGColor = m_scriptSheet.getCellBgColor(m_scriptSheet.getFirstRow(), head.getStart());
		m_notAttributeFGColor = m_scriptSheet.getCellFgColor(m_scriptSheet.getFirstRow(), head.getStart());
		if(m_notAttributeBGColor == Config.NO_COLOR || m_notAttributeFGColor == Config.NO_COLOR)
		{
			throw new ErrorException(ErrorDefine.E_SCRIPT_SHEET_ERROR, m_scriptSheetName, Config.NO_POSITION);
		}
		for(ExcelType type: ExcelType.values())
		{
			head = m_scriptSheet.hasExcelTypeHead(type);
			if(head != null)
			{
				ArrayList<String> list = m_scriptSheet.getContentOfHead(head);
				addNameToSheetNames(type, list);
			}
		}
		setExcelType();
		for(int i = 0; i < len; ++i)
		{	
			String name = m_workBook.getSheet(i).getName();
			if(name.compareTo(m_scriptSheetName) == 0)
			{
				continue;
			}
			if(hasChild(name) != Config.NO_FIND)
			{
				new WarningHandler(WarningDefine.E_SHEET_WITH_SAME_NAME_WARNING, m_workBook.getSheet(i).getName()).showWarning();
			}
			ExcelType type = m_type;
			if(type == null)
			{
				type = findExcelTypeByName(name);
			}
			Sheet sheet = new Sheet(m_workBook.getSheet(i), type, this);
			sheet.init();
			m_children.add(sheet);
		}
	}
	
	private void addNameToSheetNames(ExcelType type, ArrayList<String> names)
	{
		ArrayList<String> list = m_sheetNames.get(type);
		if(list == null)
		{
			list = new ArrayList<>();
			m_sheetNames.put(type, list);
		}
		for(String temp: names)
		{
			list.add(temp);
		}
	}
	
	private void setExcelType()
	{
		boolean singelType = true;
		for(ExcelType type: ExcelType.values())
		{
			ArrayList<String> list = m_sheetNames.get(type);
			if(list != null)
			{
				if(list.size() == 0)
				{
					m_type = type;
					return;
				}
				singelType = false;
				break;
			}
		}
		if(singelType)
		{
			m_type = Config.EXCEL_DEFAUT_TYPE;
		}
	}
	
	private ExcelType findExcelTypeByName(String name)
	{
		for(ExcelType type: ExcelType.values())
		{
			ArrayList<String> list = m_sheetNames.get(type);
			if(list == null)
			{
				continue;
			}
			for(String temp: list)
			{
				if(temp.compareTo(name) == 0)
				{
					return type;
				}
			}
		}
		return Config.EXCEL_DEFAUT_TYPE;
	}
	
	public void compileScript() throws ErrorException
	{
		if(m_scriptSheet.hasHead(Config.SCRIPT_NAME) == null || m_scriptSheet.hasHead(Config.SCRIPT_OUTPUT) == null)
		{
			throw new ErrorException(ErrorDefine.E_SCRIPT_SHEET_ERROR, m_scriptSheetName, Config.NO_POSITION);
		}
		m_scripts = new ArrayList<>();
		for(int i = 0, max = m_scriptSheet.getChildNumber(); i < max; ++i)
		{
			BaseContent row = m_scriptSheet.getChild(i, Config.NO_POSITION);
			String name = row.getChild(Config.SCRIPT_NAME, Config.NO_POSITION).getChild(0, Config.NO_POSITION).getName();
			if(name.length() == 0)
			{
				continue;
			}
			String out = row.getChild(Config.SCRIPT_OUTPUT, Config.NO_POSITION).getChild(0, Config.NO_POSITION).getName();
			Script temp = new Script(name, this, out);
			ErrorHandler.m_errorScript = temp;
			temp.init();
			m_scripts.add(temp);		
		}
	}
	
	public void output() throws ErrorException
	{
		for(Script temp: m_scripts)
		{
			ErrorHandler.m_errorScript = temp;
			temp.saveToFile(temp.getValue());
		}
	}
	
	public Script getScript(String name)
	{
		for(Script temp: m_scripts)
		{
			if(name.compareTo(temp.getName()) == 0)
			{
				return temp;
			}
		}
		return null;
	}
	
	public short getNotAttributeBGColor()
	{
		return m_notAttributeBGColor;
	}
	
	public short getNotAttributeFGColor()
	{
		return m_notAttributeFGColor;
	}
	
	public String getName()
	{
		return m_name;
	}
	
	public String getPath()
	{
		return m_path;
	}
	
	public SheetInLib addSheet(String name, int position) throws ErrorException
	{
		return m_workBook.addSheet(name, position);
	}
	
	public void writeToExecl(int position) throws ErrorException
	{
		m_workBook.write(position);
	}
}
